package com.pt.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pt.dto.request.TorrentUploadRequest;
import com.pt.common.ApiResponse;
import com.pt.entity.Torrent;
import com.pt.entity.User;
import com.pt.service.TorrentService;
import com.pt.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import com.pt.utils.SecurityUtils;
import com.pt.common.constant.TorrentConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RestController
@RequestMapping("/api/torrents")
@RequiredArgsConstructor
@Api(tags = "种子管理")
public class TorrentController {

    private final TorrentService torrentService;
    private final UserService userService;
    private static final Logger log = LoggerFactory.getLogger(TorrentController.class);

    @GetMapping
    @ApiOperation("获取种子列表")
    public ApiResponse<Page<Torrent>> listTorrents(
            @ApiParam("分类") @RequestParam(required = false) String category,
            @ApiParam("关键词") @RequestParam(required = false) String keyword,
            @ApiParam("是否只看促销") @RequestParam(required = false, defaultValue = "false") Boolean promotionOnly,
            @ApiParam("页码") @RequestParam(defaultValue = "1") int page,
            @ApiParam("每页数量") @RequestParam(defaultValue = "10") int size) {
        
        System.out.println("=== TorrentController.listTorrents被调用 ===");
        System.out.println("分类: " + category);
        System.out.println("关键词: " + keyword);
        System.out.println("页码: " + page + ", 每页数量: " + size);
        
        try {
            Page<Torrent> result = torrentService.listTorrents(category, keyword, promotionOnly, page, size);
            System.out.println("查询到种子数量: " + result.getRecords().size());
            
            // 为每个种子设置上传者用户名和分类名称
            for (Torrent torrent : result.getRecords()) {
                System.out.println("种子ID: " + torrent.getId());
                System.out.println("种子标题: " + torrent.getTitle());
                
                // 设置上传者用户名
                if (torrent.getUploaderId() != null) {
                    try {
                        User uploader = userService.getById(torrent.getUploaderId());
                        if (uploader != null) {
                            torrent.setUploaderName(uploader.getUsername());
                            System.out.println("设置上传者: " + uploader.getUsername());
                        } else {
                            torrent.setUploaderName("未知用户");
                            System.out.println("未找到上传者信息");
                        }
                    } catch (Exception e) {
                        System.out.println("获取上传者信息时出错: " + e.getMessage());
                        torrent.setUploaderName("未知用户");
                    }
                } else {
                    torrent.setUploaderName("未知用户");
                    System.out.println("上传者ID为空");
                }
                
                // 设置分类名称
                if (torrent.getCategoryId() != null && (torrent.getCategory() == null || torrent.getCategory().isEmpty())) {
                    String categoryName = getCategoryNameById(torrent.getCategoryId());
                    torrent.setCategory(categoryName);
                    System.out.println("设置分类名称: " + categoryName + " (ID: " + torrent.getCategoryId() + ")");
                } else if (torrent.getCategory() != null) {
                    System.out.println("已有分类名称: " + torrent.getCategory());
                }
                
                // 处理描述字段
                if (torrent.getDescription() != null) {
                    System.out.println("描述字段类型: " + torrent.getDescription().getClass().getName());
                    System.out.println("描述长度: " + torrent.getDescription().length());
                    System.out.println("描述内容（前100字符）: " + torrent.getDescription().substring(0, Math.min(torrent.getDescription().length(), 100)));
                    
                    // 检查是否包含非打印字符
                    boolean hasNonPrintable = torrent.getDescription().chars().anyMatch(c -> c < 32 && c != 9 && c != 10 && c != 13);
                    System.out.println("包含非打印字符: " + hasNonPrintable);
                }
            }
            
            System.out.println("创建ApiResponse成功，准备返回");
            ApiResponse<Page<Torrent>> response = ApiResponse.success(result);
            System.out.println("响应code: " + response.getCode());
            System.out.println("响应message: " + response.getMessage());
            System.out.println("响应data类型: " + response.getData().getClass().getName());
            
            // 测试JSON序列化
            try {
                com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
                // 配置Jackson处理Java 8时间类型
                mapper.registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule());
                mapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
                
                String jsonString = mapper.writeValueAsString(response);
                System.out.println("JSON序列化成功，长度: " + jsonString.length());
                System.out.println("JSON前200字符: " + jsonString.substring(0, Math.min(jsonString.length(), 200)));
            } catch (Exception e) {
                System.out.println("JSON序列化失败: " + e.getMessage());
                e.printStackTrace();
                // 如果序列化失败，返回简化的响应
                return ApiResponse.error("种子数据序列化失败");
            }
            
            return response;
        } catch (Exception e) {
            System.out.println("获取种子列表发生异常: " + e.getMessage());
            e.printStackTrace();
            return ApiResponse.error("获取种子列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}")
    @ApiOperation("获取种子详情")
    public ApiResponse<Torrent> getTorrent(
            @ApiParam("种子ID") @PathVariable Long id) {
        try {
            Torrent torrent = torrentService.getTorrent(id);
            if (torrent != null) {
                // 设置上传者用户名
                if (torrent.getUploaderId() != null) {
                    try {
                        User uploader = userService.getById(torrent.getUploaderId());
                        if (uploader != null) {
                            torrent.setUploaderName(uploader.getUsername());
                        } else {
                            torrent.setUploaderName("未知用户");
                        }
                    } catch (Exception e) {
                        torrent.setUploaderName("未知用户");
                    }
                } else {
                    torrent.setUploaderName("未知用户");
                }
                
                // 设置分类名称
                if (torrent.getCategoryId() != null && (torrent.getCategory() == null || torrent.getCategory().isEmpty())) {
                    String categoryName = getCategoryNameById(torrent.getCategoryId());
                    torrent.setCategory(categoryName);
                }
            }
            return ApiResponse.success(torrent);
        } catch (Exception e) {
            return ApiResponse.error("获取种子详情失败: " + e.getMessage());
        }
    }

    @PostMapping
    @ApiOperation("上传种子")
    @PreAuthorize("isAuthenticated()")
    public ApiResponse<Torrent> uploadTorrent(
            @ApiParam("种子文件") @RequestParam("file") MultipartFile file,
            @ApiParam("种子标题") @RequestParam String title,
            @ApiParam("种子描述") @RequestParam String description,
            @ApiParam("种子分类") @RequestParam String category) {
        
        System.out.println("=== 种子上传API被调用 ===");
        System.out.println("文件名: " + file.getOriginalFilename());
        System.out.println("文件大小: " + file.getSize());
        System.out.println("标题: " + title);
        System.out.println("分类: " + category);
        
        try {
            // 创建TorrentUploadRequest对象
            TorrentUploadRequest request = new TorrentUploadRequest();
            request.setTitle(title);
            request.setDescription(description);
            request.setCategoryId(getCategoryId(category));
            request.setFile(file);
            
            System.out.println("分类ID: " + request.getCategoryId());
            
            // 获取当前用户
            User currentUser = userService.getCurrentUser();
            System.out.println("当前用户: " + currentUser.getUsername());
            
            // 上传种子
            Torrent result = torrentService.uploadTorrent(request, currentUser.getId());
            System.out.println("种子上传完成，返回结果");
            
            return ApiResponse.success(result);
        } catch (Exception e) {
            System.out.println("Controller层捕获异常: " + e.getMessage());
            e.printStackTrace();
            return ApiResponse.error(e.getMessage());
        }
    }
    
    // 根据分类名称获取分类ID
    private Integer getCategoryId(String category) {
        if (category == null || category.trim().isEmpty()) {
            return 1; // 默认分类
        }
        
        // 根据分类名称映射到ID
        switch (category) {
            case "电影":
                return 1;
            case "电视剧":
                return 2;
            case "音乐":
                return 3;
            case "软件":
                return 4;
            case "游戏":
                return 5;
            case "电子书":
                return 6;
            case "动漫":
                return 7;
            case "其他":
                return 8;
            default:
                return 1; // 默认分类
        }
    }
    
    // 根据分类ID获取分类名称
    private String getCategoryNameById(Integer categoryId) {
        if (categoryId == null) {
            return "其他";
        }
        
        switch (categoryId) {
            case 1:
                return "电影";
            case 2:
                return "电视剧";
            case 3:
                return "音乐";
            case 4:
                return "软件";
            case 5:
                return "游戏";
            case 6:
                return "电子书";
            case 7:
                return "动漫";
            case 8:
                return "其他";
            default:
                return "其他";
        }
    }

    @GetMapping("/my")
    @ApiOperation("获取当前用户上传的种子列表")
    @PreAuthorize("isAuthenticated()")
    public ApiResponse<Page<Torrent>> getMyTorrents(
            @ApiParam("页码") @RequestParam(defaultValue = "1") int page,
            @ApiParam("每页数量") @RequestParam(defaultValue = "10") int size) {
        
        try {
            User currentUser = userService.getCurrentUser();
            Page<Torrent> result = torrentService.getUserTorrents(currentUser.getId(), page, size);
            
            // 为每个种子设置上传者用户名和分类名称
            for (Torrent torrent : result.getRecords()) {
                torrent.setUploaderName(currentUser.getUsername());
                
                // 设置分类名称
                if (torrent.getCategoryId() != null && (torrent.getCategory() == null || torrent.getCategory().isEmpty())) {
                    String categoryName = getCategoryNameById(torrent.getCategoryId());
                    torrent.setCategory(categoryName);
                }
            }
            
            return ApiResponse.success(result);
        } catch (Exception e) {
            return ApiResponse.error("获取我的种子列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/download/{id}")
    public void downloadTorrent(@PathVariable Long id, HttpServletResponse response) {
        log.info("开始处理种子下载请求 - 种子ID: {}", id);
        
        // 获取当前用户
        Long userId = SecurityUtils.getCurrentUserId();
        log.info("当前用户ID: {}", userId);
        
        // 检查下载限制
        if (!userService.checkDownloadLimit(userId)) {
            log.warn("用户已达到今日下载限制 - 用户ID: {}", userId);
            throw new RuntimeException("您已达到今日下载限制");
        }
        
        // 获取种子信息
        Torrent torrent = torrentService.getById(id);
        if (torrent == null) {
            log.error("种子不存在 - 种子ID: {}", id);
            throw new RuntimeException("种子不存在");
        }
        
        // 更新用户统计数据（种子大小作为下载量）
        userService.updateUserStats(userId, 0L, torrent.getSize());
        log.info("更新用户统计数据 - 用户ID: {}, 下载量: {}", userId, torrent.getSize());
        
        // 先记录下载，如果记录失败则不允许下载
        try {
            userService.recordDownload(userId, id);
            log.info("下载记录完成");
        } catch (Exception e) {
            log.error("记录下载失败 - 用户ID: {}, 种子ID: {}, 错误: {}", userId, id, e.getMessage());
            throw new RuntimeException("记录下载失败", e);
        }
        
        // 下载文件
        try {
            String filePath = TorrentConstant.TORRENT_SAVE_PATH + torrent.getInfoHash() + ".torrent";
            File file = new File(filePath);
            if (!file.exists()) {
                log.error("种子文件不存在 - 路径: {}", filePath);
                throw new RuntimeException("种子文件不存在");
            }
            
            response.setContentType("application/x-bittorrent");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(torrent.getTitle() + ".torrent", "UTF-8"));
            
            try (FileInputStream fis = new FileInputStream(file);
                 OutputStream out = response.getOutputStream()) {
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                }
            }
        } catch (IOException e) {
            log.error("下载失败 - 用户ID: {}, 种子ID: {}, 错误: {}", userId, id, e.getMessage());
            throw new RuntimeException("下载失败", e);
        }
    }

    @DeleteMapping("/{id}")
    @ApiOperation("删除种子")
    @PreAuthorize("isAuthenticated()")
    public ApiResponse<Void> deleteTorrent(@ApiParam("种子ID") @PathVariable Long id) {
        System.out.println("=== 删除种子控制器被调用 ===");
        System.out.println("种子ID: " + id);
        
        try {
            // 获取当前用户
            User currentUser = userService.getCurrentUser();
            System.out.println("当前用户: " + currentUser.getUsername());
            
            // 执行删除
            torrentService.deleteTorrent(id, currentUser.getId());
            
            System.out.println("种子删除成功");
            return ApiResponse.success(null);
        } catch (Exception e) {
            System.out.println("ERROR: 删除种子失败: " + e.getMessage());
            e.printStackTrace();
            return ApiResponse.error("删除失败：" + e.getMessage());
        }
    }

    @PutMapping("/{id}/promotion")
    @ApiOperation("设置促销(管理员)")
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResponse<Void> setPromotion(
            @ApiParam("种子ID") @PathVariable Long id,
            @ApiParam("促销类型") @RequestParam Integer promotionType,
            @ApiParam("促销持续小时数") @RequestParam Integer durationHours) {
        try {
            torrentService.setPromotion(id, promotionType, durationHours);
            return ApiResponse.success(null);
        } catch (Exception e) {
            return ApiResponse.error(e.getMessage());
        }
    }
} 